package com.fmsh.nfcsensor.utils;

import com.fmsh.base.utils.FMUtil;
import com.fmsh.base.utils.LogUtil;
import com.fmsh.nfcsensor.bean.GasIndexAlgorithmParams;

/**
 * @author wuyajiang
 * @date 2022/11/10
 */
public class SensorUtils {

    public static double[] parse_sensor_data(byte[] reg_data, byte[] dev) {
        double[] result = new double[2];
        int data_msb = (int) getUint8(reg_data[0]) << 12;
        int data_lsb = (int) getUint8(reg_data[1]) << 4;
        int data_xlsb = (int) getUint8(reg_data[2]) >> 4;

        double pressure = data_msb | data_lsb | data_xlsb;

        data_msb = (int) getUint8(reg_data[3]) << 12;
        data_lsb = (int) getUint8(reg_data[4]) << 4;
        data_xlsb = (int) getUint8(reg_data[5]) >> 4;


        double temperature = (int) (data_msb | data_lsb | data_xlsb);

        double[] t_fine = new double[1];
        result[0] = compensate_temperature(temperature, dev, t_fine);

        LogUtil.d(result[0]);
        result[1] = compensate_pressure(pressure, dev, t_fine);
        LogUtil.d(result[1]);
        return result;

    }


    public static double compensate_temperature(double data, byte[] dev, double[] t_fine) {
        double var1, var2;
        double temperature;
        var1 = (((double) data) / 16384.0 - ((double) byteArrayToUnsignedInt(new byte[]{dev[1], dev[0]})) / 1024.0) *
                ((double) byteArrayToInt(new byte[]{dev[3], dev[2]}));
        var2 =
                ((((double) data) / 131072.0 - ((double) byteArrayToUnsignedInt(new byte[]{dev[1], dev[0]})) / 8192.0) *
                        (((double) data) / 131072.0 - ((double) byteArrayToUnsignedInt(new byte[]{dev[1], dev[0]})) / 8192.0)) *
                        ((double) byteArrayToInt(new byte[]{dev[5], dev[4]}));

        t_fine[0] = (int) (var1 + var2);
        temperature = (var1 + var2) / 5120.0;

        if (temperature < Constants.BMP2_MIN_TEMP_DOUBLE) {
            temperature = Constants.BMP2_MIN_TEMP_DOUBLE;
            //rslt = BMP2_W_MIN_TEMP;
        }

        if (temperature > Constants.BMP2_MAX_TEMP_DOUBLE) {
            temperature = Constants.BMP2_MAX_TEMP_DOUBLE;
            //rslt = BMP2_W_MAX_TEMP;
        }

        return temperature;
    }

    public static double compensate_pressure(double data, byte[] dev, double[] t_fine) {

        double var1, var2;
        double pressure = 0.0;
        double p6 = (double) byteArrayToInt(new byte[]{dev[17], dev[16]});

        double p5 = (double) byteArrayToInt(new byte[]{dev[15], dev[14]});
        var1 = ((double) t_fine[0] / 2.0) - 64000.0;
        var2 = var1 * var1 * (p6) / 32768.0;
        var2 = var2 + var1 * (p5) * 2.0;
        var2 = (var2 / 4.0) + (((double) byteArrayToInt(new byte[]{dev[13], dev[12]})) * 65536.0);
        var1 = (((double) byteArrayToInt(new byte[]{dev[11], dev[10]})) * var1 * var1 / 524288.0 + ((double) byteArrayToInt(new byte[]{dev[9], dev[8]})) * var1) /
                524288.0;
        var1 = (1.0 + var1 / 32768.0) * ((double) byteArrayToUnsignedInt(new byte[]{dev[7], dev[6]}));

        if (var1 < 0 || var1 > 0) {
            pressure = 1048576.0 - data;
            pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1;
            var1 = ((double) byteArrayToInt(new byte[]{dev[23], dev[22]})) * pressure * pressure / 2147483648.0;
            var2 = pressure * ((double) byteArrayToInt(new byte[]{dev[21], dev[20]})) / 32768.0;

            pressure = pressure + (var1 + var2 + ((double) byteArrayToInt(new byte[]{dev[19], dev[18]}))) / 16.0;

            if (pressure < Constants.BMP2_MIN_PRES_DOUBLE) {
                pressure = Constants.BMP2_MIN_PRES_DOUBLE;
                // rslt = BMP2_W_MIN_PRES;
            }

            if (pressure > Constants.BMP2_MAX_PRES_DOUBLE) {
                pressure = Constants.BMP2_MAX_PRES_DOUBLE;
                //rslt = BMP2_W_MAX_PRES;
            }

        }

        return pressure;

    }
  public static   void GasIndexAlgorithm_init(GasIndexAlgorithmParams params, int algorithm_type) {
        GasIndexAlgorithm_init_with_sampling_interval(
                params, algorithm_type, Constants.GasIndexAlgorithm_DEFAULT_SAMPLING_INTERVAL);
    }

  public static   void GasIndexAlgorithm_init_with_sampling_interval(
            GasIndexAlgorithmParams params, int algorithm_type,
            float sampling_interval) {
        params.mAlgorithm_Type = algorithm_type;
        params.mSamplingInterval = sampling_interval;
        if ((algorithm_type == Constants.GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) {
            params.mIndex_Offset = Constants.GasIndexAlgorithm_NOX_INDEX_OFFSET_DEFAULT;
            params.mSraw_Minimum = Constants.GasIndexAlgorithm_NOX_SRAW_MINIMUM;
            params.mGating_Max_Duration_Minutes =
                    Constants.GasIndexAlgorithm_GATING_NOX_MAX_DURATION_MINUTES;
            params.mInit_Duration_Mean = Constants.GasIndexAlgorithm_INIT_DURATION_MEAN_NOX;
            params.mInit_Duration_Variance =
                    Constants.GasIndexAlgorithm_INIT_DURATION_VARIANCE_NOX;
            params.mGating_Threshold = Constants.GasIndexAlgorithm_GATING_THRESHOLD_NOX;
        } else {
            params.mIndex_Offset = Constants.GasIndexAlgorithm_VOC_INDEX_OFFSET_DEFAULT;
            params.mSraw_Minimum = Constants.GasIndexAlgorithm_VOC_SRAW_MINIMUM;
            params.mGating_Max_Duration_Minutes =
                    Constants.GasIndexAlgorithm_GATING_VOC_MAX_DURATION_MINUTES;
            params.mInit_Duration_Mean = Constants.GasIndexAlgorithm_INIT_DURATION_MEAN_VOC;
            params.mInit_Duration_Variance =
                    Constants.GasIndexAlgorithm_INIT_DURATION_VARIANCE_VOC;
            params.mGating_Threshold = Constants.GasIndexAlgorithm_GATING_THRESHOLD_VOC;
        }
        params.mIndex_Gain = Constants.GasIndexAlgorithm_INDEX_GAIN;
        params.mTau_Mean_Hours = Constants.GasIndexAlgorithm_TAU_MEAN_HOURS;
        params.mTau_Variance_Hours = Constants.GasIndexAlgorithm_TAU_VARIANCE_HOURS;
        params.mSraw_Std_Initial = Constants.GasIndexAlgorithm_SRAW_STD_INITIAL;
       GasIndexAlgorithm_reset(params);
    }

    public static void GasIndexAlgorithm_reset(GasIndexAlgorithmParams params) {
        params.mUptime = 0.f;
        params.mSraw = 0.f;
        params.mGas_Index = 0;
        GasIndexAlgorithm__init_instances(params);
    }

    public static void GasIndexAlgorithm__init_instances(GasIndexAlgorithmParams params) {
        GasIndexAlgorithm__mean_variance_estimator__set_parameters(params);
        GasIndexAlgorithm__mox_model__set_parameters(
                params, GasIndexAlgorithm__mean_variance_estimator__get_std(params),
                GasIndexAlgorithm__mean_variance_estimator__get_mean(params));
        if ((params.mAlgorithm_Type == Constants.GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) {
            GasIndexAlgorithm__sigmoid_scaled__set_parameters(
                    params, Constants.GasIndexAlgorithm_SIGMOID_X0_NOX,
                    Constants.GasIndexAlgorithm_SIGMOID_K_NOX,
                    Constants.GasIndexAlgorithm_NOX_INDEX_OFFSET_DEFAULT);
        } else {
            GasIndexAlgorithm__sigmoid_scaled__set_parameters(
                    params, Constants.GasIndexAlgorithm_SIGMOID_X0_VOC,
                    Constants.GasIndexAlgorithm_SIGMOID_K_VOC,
                    Constants.GasIndexAlgorithm_VOC_INDEX_OFFSET_DEFAULT);
        }
        GasIndexAlgorithm__adaptive_lowpass__set_parameters(params);
    }

    public static void GasIndexAlgorithm__mean_variance_estimator__set_parameters(GasIndexAlgorithmParams params) {
        params.m_Mean_Variance_Estimator___Initialized = false;
        params.m_Mean_Variance_Estimator___Mean = 0.f;
        params.m_Mean_Variance_Estimator___Sraw_Offset = 0.f;
        params.m_Mean_Variance_Estimator___Std = params.mSraw_Std_Initial;
        params.m_Mean_Variance_Estimator___Gamma_Mean =
                (((Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING *
                        Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) *
                        (params.mSamplingInterval / 3600.f)) /
                        (params.mTau_Mean_Hours + (params.mSamplingInterval / 3600.f)));
        params.m_Mean_Variance_Estimator___Gamma_Variance =
                ((Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING *
                        (params.mSamplingInterval / 3600.f)) /
                        (params.mTau_Variance_Hours + (params.mSamplingInterval / 3600.f)));
        if ((params.mAlgorithm_Type == Constants.GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) {
            params.m_Mean_Variance_Estimator___Gamma_Initial_Mean =
                    (((Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING *
                            Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) *
                            params.mSamplingInterval) /
                            (Constants.GasIndexAlgorithm_TAU_INITIAL_MEAN_NOX +
                                    params.mSamplingInterval));
        } else {
            params.m_Mean_Variance_Estimator___Gamma_Initial_Mean =
                    (((Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING *
                            Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) *
                            params.mSamplingInterval) /
                            (Constants.GasIndexAlgorithm_TAU_INITIAL_MEAN_VOC +
                                    params.mSamplingInterval));
        }
        params.m_Mean_Variance_Estimator___Gamma_Initial_Variance =
                ((Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING *
                        params.mSamplingInterval) /
                        (Constants.GasIndexAlgorithm_TAU_INITIAL_VARIANCE + params.mSamplingInterval));
        params.m_Mean_Variance_Estimator__Gamma_Mean = 0.f;
        params.m_Mean_Variance_Estimator__Gamma_Variance = 0.f;
        params.m_Mean_Variance_Estimator___Uptime_Gamma = 0.f;
        params.m_Mean_Variance_Estimator___Uptime_Gating = 0.f;
        params.m_Mean_Variance_Estimator___Gating_Duration_Minutes = 0.f;
    }

    public static void
    GasIndexAlgorithm__mox_model__set_parameters(GasIndexAlgorithmParams params,
                                                 float SRAW_STD, float SRAW_MEAN) {
        params.m_Mox_Model__Sraw_Std = SRAW_STD;
        params.m_Mox_Model__Sraw_Mean = SRAW_MEAN;
    }

    public static float GasIndexAlgorithm__mean_variance_estimator__get_std(
            GasIndexAlgorithmParams params) {
        return params.m_Mean_Variance_Estimator___Std;
    }

    public static float GasIndexAlgorithm__mean_variance_estimator__get_mean(
            GasIndexAlgorithmParams params) {

        return (params.m_Mean_Variance_Estimator___Mean +
                params.m_Mean_Variance_Estimator___Sraw_Offset);
    }

    public static void GasIndexAlgorithm__sigmoid_scaled__set_parameters(
            GasIndexAlgorithmParams params, float X0, float K, float offset_default) {

        params.m_Sigmoid_Scaled__K = K;
        params.m_Sigmoid_Scaled__X0 = X0;
        params.m_Sigmoid_Scaled__Offset_Default = offset_default;
    }

    public static void GasIndexAlgorithm__adaptive_lowpass__set_parameters(
            GasIndexAlgorithmParams params) {

        params.m_Adaptive_Lowpass__A1 =
                (params.mSamplingInterval /
                        (Constants.GasIndexAlgorithm_LP_TAU_FAST + params.mSamplingInterval));
        params.m_Adaptive_Lowpass__A2 =
                (params.mSamplingInterval /
                        (Constants.GasIndexAlgorithm_LP_TAU_SLOW + params.mSamplingInterval));
        params.m_Adaptive_Lowpass___Initialized = false;
    }


    public static int GasIndexAlgorithm_process(GasIndexAlgorithmParams params, int sraw
    ) {
        int gas_index;
        if ((params.mUptime <= Constants.GasIndexAlgorithm_INITIAL_BLACKOUT)) {
            params.mUptime = (params.mUptime + params.mSamplingInterval);
        } else {
            if (((sraw > 0) && (sraw < 65000))) {
                if ((sraw < (params.mSraw_Minimum + 1))) {
                    sraw = (params.mSraw_Minimum + 1);
                } else if ((sraw > (params.mSraw_Minimum + 32767))) {
                    sraw = (params.mSraw_Minimum + 32767);
                }
                params.mSraw = ((float) ((sraw - params.mSraw_Minimum)));
            }
            if (((params.mAlgorithm_Type ==
                    Constants.GasIndexAlgorithm_ALGORITHM_TYPE_VOC) ||
                    GasIndexAlgorithm__mean_variance_estimator__is_initialized(
                            params))) {
                params.mGas_Index =
                        GasIndexAlgorithm__mox_model__process(params, params.mSraw);
                params.mGas_Index = GasIndexAlgorithm__sigmoid_scaled__process(
                        params, params.mGas_Index);
            } else {
                params.mGas_Index = params.mIndex_Offset;
            }
            params.mGas_Index = GasIndexAlgorithm__adaptive_lowpass__process(
                    params, params.mGas_Index);
            if ((params.mGas_Index < 0.5f)) {
                params.mGas_Index = 0.5f;
            }
            if ((params.mSraw > 0.f)) {
                GasIndexAlgorithm__mean_variance_estimator__process(params,
                        params.mSraw);
                GasIndexAlgorithm__mox_model__set_parameters(
                        params,
                        GasIndexAlgorithm__mean_variance_estimator__get_std(params),
                        GasIndexAlgorithm__mean_variance_estimator__get_mean(params));
            }
        }
        gas_index = ((int) ((params.mGas_Index + 0.5f)));
        return gas_index;
    }

    public static boolean GasIndexAlgorithm__mean_variance_estimator__is_initialized(
            GasIndexAlgorithmParams params) {

        return params.m_Mean_Variance_Estimator___Initialized;
    }

    public static float
    GasIndexAlgorithm__mox_model__process(GasIndexAlgorithmParams params,
                                          float sraw) {

        if ((params.mAlgorithm_Type == Constants.GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) {
            return (((sraw - params.m_Mox_Model__Sraw_Mean) /
                    Constants.GasIndexAlgorithm_SRAW_STD_NOX) *
                    params.mIndex_Gain);
        } else {
            return (((sraw - params.m_Mox_Model__Sraw_Mean) /
                    (-1.f * (params.m_Mox_Model__Sraw_Std +
                            Constants.GasIndexAlgorithm_SRAW_STD_BONUS_VOC))) *
                    params.mIndex_Gain);
        }
    }

    public static float
    GasIndexAlgorithm__sigmoid_scaled__process(GasIndexAlgorithmParams params,
                                               float sample) {

        float x;
        float shift;

        x = (params.m_Sigmoid_Scaled__K * (sample - params.m_Sigmoid_Scaled__X0));
        if ((x < -50.f)) {
            return Constants.GasIndexAlgorithm_SIGMOID_L;
        } else if ((x > 50.f)) {
            return 0.f;
        } else {
            if ((sample >= 0.f)) {
                if ((params.m_Sigmoid_Scaled__Offset_Default == 1.f)) {
                    shift = ((500.f / 499.f) * (1.f - params.mIndex_Offset));
                } else {
                    shift = ((Constants.GasIndexAlgorithm_SIGMOID_L -
                            (5.f * params.mIndex_Offset)) /
                            4.f);
                }
                return (((Constants.GasIndexAlgorithm_SIGMOID_L + shift) / (1.f + (float) Math.exp(x))) -
                        shift);
            } else {
                return  ((params.mIndex_Offset /
                        params.m_Sigmoid_Scaled__Offset_Default) *
                        (Constants.GasIndexAlgorithm_SIGMOID_L / (1.f + (float)Math.exp(x))));
            }
        }
    }

    static float
    GasIndexAlgorithm__adaptive_lowpass__process(GasIndexAlgorithmParams params,
                                                 float sample) {

        float abs_delta;
        float F1;
        float tau_a;
        float a3;

        if (!params.m_Adaptive_Lowpass___Initialized ) {
            params.m_Adaptive_Lowpass___X1 = sample;
            params.m_Adaptive_Lowpass___X2 = sample;
            params.m_Adaptive_Lowpass___X3 = sample;
            params.m_Adaptive_Lowpass___Initialized = true;
        }
        params.m_Adaptive_Lowpass___X1 =
                (((1.f - params.m_Adaptive_Lowpass__A1) *
                        params.m_Adaptive_Lowpass___X1) +
                        (params.m_Adaptive_Lowpass__A1 * sample));
        params.m_Adaptive_Lowpass___X2 =
                (((1.f - params.m_Adaptive_Lowpass__A2) *
                        params.m_Adaptive_Lowpass___X2) +
                        (params.m_Adaptive_Lowpass__A2 * sample));
        abs_delta =
                (params.m_Adaptive_Lowpass___X1 - params.m_Adaptive_Lowpass___X2);
        if ((abs_delta < 0.f)) {
            abs_delta = (-1.f * abs_delta);
        }
        F1 = (float) Math.exp((Constants.GasIndexAlgorithm_LP_ALPHA * abs_delta));
        tau_a = (((Constants.GasIndexAlgorithm_LP_TAU_SLOW - Constants.GasIndexAlgorithm_LP_TAU_FAST) *
                F1) +
                Constants.GasIndexAlgorithm_LP_TAU_FAST);
        a3 = (params.mSamplingInterval / (params.mSamplingInterval + tau_a));
        params.m_Adaptive_Lowpass___X3 =
                (((1.f - a3) * params.m_Adaptive_Lowpass___X3) + (a3 * sample));
        return params.m_Adaptive_Lowpass___X3;
    }

    static void GasIndexAlgorithm__mean_variance_estimator__process(
            GasIndexAlgorithmParams params, float sraw) {

        float delta_sgp;
        float c;
        float additional_scaling;

        if (!params.m_Mean_Variance_Estimator___Initialized) {
            params.m_Mean_Variance_Estimator___Initialized = true;
            params.m_Mean_Variance_Estimator___Sraw_Offset = sraw;
            params.m_Mean_Variance_Estimator___Mean = 0.f;
        } else {
            if (((params.m_Mean_Variance_Estimator___Mean >= 100.f) ||
                    (params.m_Mean_Variance_Estimator___Mean <= -100.f))) {
                params.m_Mean_Variance_Estimator___Sraw_Offset =
                        (params.m_Mean_Variance_Estimator___Sraw_Offset +
                                params.m_Mean_Variance_Estimator___Mean);
                params.m_Mean_Variance_Estimator___Mean = 0.f;
            }
            sraw = (sraw - params.m_Mean_Variance_Estimator___Sraw_Offset);
            GasIndexAlgorithm__mean_variance_estimator___calculate_gamma(params);
            delta_sgp = ((sraw - params.m_Mean_Variance_Estimator___Mean) /
                    Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING);
            if ((delta_sgp < 0.f)) {
                c = (params.m_Mean_Variance_Estimator___Std - delta_sgp);
            } else {
                c = (params.m_Mean_Variance_Estimator___Std + delta_sgp);
            }
            additional_scaling = 1.f;
            if ((c > 1440.f)) {
                additional_scaling = ((c / 1440.f) * (c / 1440.f));
            }
            params.m_Mean_Variance_Estimator___Std =
                    (float) (Math.sqrt((additional_scaling *
                            (Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING -
                                    params.m_Mean_Variance_Estimator__Gamma_Variance))) *
                            (float)Math.sqrt(
                                    ((params.m_Mean_Variance_Estimator___Std *
                                            (params.m_Mean_Variance_Estimator___Std /
                                                    (Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING *
                                                            additional_scaling))) +
                                            (((params.m_Mean_Variance_Estimator__Gamma_Variance *
                                                    delta_sgp) /
                                                    additional_scaling) *
                                                    delta_sgp))));
            params.m_Mean_Variance_Estimator___Mean =
                    (params.m_Mean_Variance_Estimator___Mean +
                            ((params.m_Mean_Variance_Estimator__Gamma_Mean * delta_sgp) /
                                    Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING));
        }
    }


    static void GasIndexAlgorithm__mean_variance_estimator___calculate_gamma(
            GasIndexAlgorithmParams params) {

        float uptime_limit;
        float sigmoid_gamma_mean;
        float gamma_mean;
        float gating_threshold_mean;
        float sigmoid_gating_mean;
        float sigmoid_gamma_variance;
        float gamma_variance;
        float gating_threshold_variance;
        float sigmoid_gating_variance;

        uptime_limit = (Constants.GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__FIX16_MAX -
                params.mSamplingInterval);
        if ((params.m_Mean_Variance_Estimator___Uptime_Gamma < uptime_limit)) {
            params.m_Mean_Variance_Estimator___Uptime_Gamma =
                    (params.m_Mean_Variance_Estimator___Uptime_Gamma +
                            params.mSamplingInterval);
        }
        if ((params.m_Mean_Variance_Estimator___Uptime_Gating < uptime_limit)) {
            params.m_Mean_Variance_Estimator___Uptime_Gating =
                    (params.m_Mean_Variance_Estimator___Uptime_Gating +
                            params.mSamplingInterval);
        }
        GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
                params, params.mInit_Duration_Mean,
                Constants.GasIndexAlgorithm_INIT_TRANSITION_MEAN);
        sigmoid_gamma_mean =
                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                        params, params.m_Mean_Variance_Estimator___Uptime_Gamma);
        gamma_mean = (params.m_Mean_Variance_Estimator___Gamma_Mean +
                ((params.m_Mean_Variance_Estimator___Gamma_Initial_Mean -
                        params.m_Mean_Variance_Estimator___Gamma_Mean) *
                        sigmoid_gamma_mean));
        gating_threshold_mean =
                (params.mGating_Threshold +
                        ((Constants.GasIndexAlgorithm_GATING_THRESHOLD_INITIAL -
                                params.mGating_Threshold) *
                                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                                        params, params.m_Mean_Variance_Estimator___Uptime_Gating)));
        GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
                params, gating_threshold_mean,
                Constants.GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION);
        sigmoid_gating_mean =
                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                        params, params.mGas_Index);
        params.m_Mean_Variance_Estimator__Gamma_Mean =
                (sigmoid_gating_mean * gamma_mean);
        GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
                params, params.mInit_Duration_Variance,
                Constants.GasIndexAlgorithm_INIT_TRANSITION_VARIANCE);
        sigmoid_gamma_variance =
                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                        params, params.m_Mean_Variance_Estimator___Uptime_Gamma);
        gamma_variance =
                (params.m_Mean_Variance_Estimator___Gamma_Variance +
                        ((params.m_Mean_Variance_Estimator___Gamma_Initial_Variance -
                                params.m_Mean_Variance_Estimator___Gamma_Variance) *
                                (sigmoid_gamma_variance - sigmoid_gamma_mean)));
        gating_threshold_variance =
                (params.mGating_Threshold +
                        ((Constants.GasIndexAlgorithm_GATING_THRESHOLD_INITIAL -
                                params.mGating_Threshold) *
                                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                                        params, params.m_Mean_Variance_Estimator___Uptime_Gating)));
        GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
                params, gating_threshold_variance,
                Constants.GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION);
        sigmoid_gating_variance =
                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                        params, params.mGas_Index);
        params.m_Mean_Variance_Estimator__Gamma_Variance =
                (sigmoid_gating_variance * gamma_variance);
        params.m_Mean_Variance_Estimator___Gating_Duration_Minutes =
                (params.m_Mean_Variance_Estimator___Gating_Duration_Minutes +
                        ((params.mSamplingInterval / 60.f) *
                                (((1.f - sigmoid_gating_mean) *
                                        (1.f + Constants.GasIndexAlgorithm_GATING_MAX_RATIO)) -
                                        Constants.GasIndexAlgorithm_GATING_MAX_RATIO)));
        if ((params.m_Mean_Variance_Estimator___Gating_Duration_Minutes < 0.f)) {
            params.m_Mean_Variance_Estimator___Gating_Duration_Minutes = 0.f;
        }
        if ((params.m_Mean_Variance_Estimator___Gating_Duration_Minutes >
                params.mGating_Max_Duration_Minutes)) {
            params.m_Mean_Variance_Estimator___Uptime_Gating = 0.f;
        }
    }

    public static void
    GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
            GasIndexAlgorithmParams params, float X0, float K) {

        params.m_Mean_Variance_Estimator___Sigmoid__K = K;
        params.m_Mean_Variance_Estimator___Sigmoid__X0 = X0;
    }

    public static float GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
            GasIndexAlgorithmParams params, float sample) {

        float x;

        x = (params.m_Mean_Variance_Estimator___Sigmoid__K *
                (sample - params.m_Mean_Variance_Estimator___Sigmoid__X0));
        if ((x < -50.f)) {
            return 1.f;
        } else if ((x > 50.f)) {
            return 0.f;
        } else {
            return  (1.f / (1.f + (float)Math.exp(x)));
        }
    }


    public static int byteArrayToInt(byte[] data) {
        int value;
        value = (data[0] << 8) | (getUint8(data[1]));
        LogUtil.d("byteArrayToInt", value);
        return value;
    }

    public static int byteArrayToUnsignedInt(byte[] data) {
        int value;
        value = getUint8(data[0]) * 256 + getUint8(data[1]);
        LogUtil.d("byteArrayToUnsignedInt", value);
        return value;
    }


    public static short getUint8(short s) {
        return (short) (s & 0x00ff);
    }


    public static int getUint16(int i) {
        return i & 0x0000ffff;
    }

    public static long getUint32(long l) {
        return l & 0x00000000ffffffff;
    }
}
